package it.tukano.treditor.modules;

import it.tukano.app.AbstractAppModule;
import it.tukano.app.AppModule;
import it.tukano.check.Checks;
import it.tukano.collections.History;
import it.tukano.lang.StringExt;
import it.tukano.log.Log;
import it.tukano.reflection.MethodExt;
import it.tukano.swingdeco.containers.JPanelExt;
import it.tukano.swingdeco.containers.JToolBarExt;
import it.tukano.swingdeco.controls.JButtonExt;
import it.tukano.treditor.resources.Icons;
import java.awt.BorderLayout;
import java.io.IOException;
import java.net.URL;
import javax.swing.JEditorPane;
import javax.swing.JScrollPane;

/**
 * This module manages the help system (pages, links and alike) of the program
 * @author pgi
 */
public class HelpSystemModule extends AbstractAppModule {
    private static final String BACK_ICON_NAME = "back";
    private static final String DEFAULT_PAGE_NAME = "index";
    private static final String FORTH_ICON_NAME = "forth";
    private static final String HTML_MIMETYPE = "text/html";
    private static final String DEFAULT_PAGE_EXTENSION = ".html";
    private static final String DEFAULT_BASE_FOLDER = "/it/tukano/treditor/help/html";
    private static final String TAB_LABEL = "Help";
    private static final int TOOLBAR_ICON_SIZE = 16;
    
    private JEditorPane htmlDisplay;//html display
    private final History<URL> history = new History<>();

    /**
     * Instance initializer
     */
    public HelpSystemModule() {
    }

    @Override
    public void startModule(AppModule context) {
        Checks.NotNull(context);
        MainFrame mainFrame = context.find(MainFrame.class);
        Checks.NotNull(mainFrame);
        JEditorPane display = new JEditorPane(HTML_MIMETYPE, null);
        display.setEditable(false);
        display.addHyperlinkListener(new DefaultHelpSystemHyperlinkListener(this));
        this.htmlDisplay = display;
        JScrollPane displayScroller = new JScrollPane(display);
        JPanelExt container = new JPanelExt(new BorderLayout())
                .withName(TAB_LABEL)
                .append(displayScroller, BorderLayout.CENTER)
                .append(
                    new JToolBarExt().floatable(false).append(
                        new JButtonExt().withIcon(Icons.get(BACK_ICON_NAME, TOOLBAR_ICON_SIZE)).onAction(new MethodExt(this, "historyBack")),
                        new JButtonExt(Icons.get(FORTH_ICON_NAME, TOOLBAR_ICON_SIZE)).onAction(new MethodExt(this, "historyForth"))), 
                    BorderLayout.NORTH);
        mainFrame.install(container, BorderLayout.CENTER, true);
        loadPageFromDefaultBase(DEFAULT_PAGE_NAME);
    }
    
    public void historyBack() {
        URL previous = history.loadPrevious();
        if(previous != null) getHtmlDisplay().setPage(previous, false);
    }
    
    public void historyForth() {
        URL next = history.loadNext();
        if(next != null) getHtmlDisplay().setPage(next, false);
    }
    
    /**
     * Load an html page. The page file is resolved against the default package it.tukano.treditor.help.html.
     * @param pageFileName the name of the page to load. If the name doesn't end with a .html suffix, the .html
     * suffix will be added.
     */
    public void loadPageFromDefaultBase(String pageFileName) {
        Checks.NotNull(pageFileName);
        
        pageFileName = new StringExt(pageFileName).asStringWithPrefixAndSuffix("/", DEFAULT_PAGE_EXTENSION);
        String defaultPageResourceAddress = DEFAULT_BASE_FOLDER + pageFileName;
        URL pageUrl = HelpSystemModule.class.getResource(defaultPageResourceAddress);
        if(pageUrl != null) {
            loadPage(pageUrl);
        } else {
            Log.message("Cannot find page ", pageFileName, " in default address");
        }
    }

    /* Send the url to the display component */
    private void loadPage(URL url) {
        Checks.NotNull(url);
        HtmlDisplay display = getHtmlDisplay();
        display.setPage(url, true);
    }

    /* returns the component used to display the html pages */
    private HtmlDisplay getHtmlDisplay() {
        return new HtmlDisplay() {

            public void setPage(URL url, boolean store) {
                try {
                    htmlDisplay.setPage(url);
                    if(store) {
                        history.add(url);
                    }
                } catch (IOException ex) {
                    Log.message("Cannot load page ", url, " due to exception: ", ex);
                }
            }
        };
    }
    
//abstract data types    
    private static interface HtmlDisplay {
        void setPage(URL url, boolean storeToHistory);
    }
}
